'''
@author: nick mueller
'''

import socket
import threading
import util

_com = None

def getCommunication():
    '''
    returns the communication instance.
    Please use only this function, because it is set up
    for the raspberry configuration.
    '''
    global _com
    if(_com == None):
        # Debug: '192.168.1.102'
        _com = Communication('10.1.1.254', 12005)
    
    return _com

class Communication(threading.Thread):
    '''
    The Communication class is running on a new thread and manages the
    connection to another device. The communication is build on the tcp
    socket system. 
    '''
    
    def __init__(self, ip, port):
        threading.Thread.__init__(self)
        self.socket = None
        self.running = False
        self.conn = None
        self.ip = ip
        self.port = port
        self.buffersize = 1024
        self.callbackIncoming = None
        
    def setIncomingListener(self, incomingCallback):
        '''
        set the listener (function pointer) for incoming calls.
        If a message arrives the server call the listener.
        
        Important: The listener have to ONE parameter. This parameter
                   represents the incoming data. The return value of
                   the listener will send back to device.
                   If the return value is None, no message will send
        '''
        self.callbackIncoming = incomingCallback
        
    def startCommunication(self):
        '''
        starts the communication thread. The server socket will be started.
        The socket waits for a connection.
        '''
        self.running = True
        self.start()
    
    def stopCommunication(self):
        '''
        stops the communication. The server socket will be closed.
        '''
        self.running = False
    
    def send(self, data):
        '''
        sends some data over the current connection to another device.
        '''
        if not(self.conn == None):
            try:
                self.conn.send(data)
            except Exception, e:
                util.getLogger().info('Error:' + str(e))
    
    def run(self):
        util.getLogger().info('Comm. started')
        while self.running:
            self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            self.socket.bind((self.ip, self.port))
            self.socket.listen(5)
            self.conn, addr = self.socket.accept()
            util.getLogger().info('Connection address:' + str(addr))
            
            while self.running:
                try:
                    data = self.conn.recv(self.buffersize)
                    if not data: break
                    
                    if(not(self.callbackIncoming == None)):
                        response = self.callbackIncoming(data)
                        
                        if(not(response == None)):
                            response = util.getDelimitMessage(response)
                            self.conn.send(response)
                    
                except Exception, e:
                    util.getLogger().info('Error:' + str(e))
                
            self.conn.close()
            self.conn = None
